package com.hrbxlh.util;

import com.hrbxlh.enums.HomeworkOrExpreEnum;
import com.hrbxlh.pojo.ExpreLibrary;
import com.hrbxlh.pojo.TaskLibrary;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;

/**
 * Created by Administrator on 2018/4/23.
 */
public class PubImExcel<T> {
    //日志信息
    Logger LOGGER = Logger.getLogger(PubImExcel.class.getName());

    Map<String, Field> initFieldMap(List<String> fieldNameList, Class<T> clazz) {
        Map<String, Field> fieldMap = new HashMap<>();
        for (String fieldName : fieldNameList) {
            try {
                Field field = clazz.getDeclaredField(fieldName);
                fieldMap.put(fieldName, field);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
        }
        return fieldMap;
    }

    Map<String, Object> error(String msg) {
        Map<String, Object> finalMap = new HashMap<>();
        finalMap.put("list", null);
        finalMap.put("msg", msg);
        return finalMap;
    }

    Map<String, Object> success(List<T> objects, BigDecimal homeorexpreSource) {
        Map<String, Object> finalMap = new HashMap<>();
        finalMap.put("list", objects);
        finalMap.put("actualSumSource", homeorexpreSource);
        return finalMap;
    }


    public Map<String, Object> readXlsOrXlsxFile(List<String> fieldNameList, MultipartFile file, Workbook workBook,
                                                 int startLine, Class<T> clazz) {

        Sheet sheet = workBook.getSheetAt(0);
        int lastRowNum = sheet.getLastRowNum();

        startLine--;
        if (startLine > lastRowNum) {
            return error("数据不可以为空");
        }

        Map<String, Field> fieldMap = initFieldMap(fieldNameList, clazz);

        List<T> objects = new ArrayList<>();
        BigDecimal homeorexpreSource = new BigDecimal(0);

        for (int i = startLine; i <= lastRowNum; i++) {
            Row row = sheet.getRow(i);
            if (row == null) {
                return error("数据不可以为空");
            }

            T entity;
            try {
                entity = clazz.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
                return error("系统异常");
            }

            int nullCount = 0;
            //标识题型的字段
            String typeName = null;
            String mayError = null;
            for (int j = 0; j < fieldNameList.size(); j++) {
                String fieldName = fieldNameList.get(j);
                Cell cell = row.getCell(j);

                String cellValue = getCellValue(cell);
                if (StringUtils.isBlank(cellValue)) {
                    nullCount++;
                }

                if(j==1){
                    typeName = cellValue;
                }
                Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
                if(mayError == null){
                    String result = setFields(entity, fieldMap.get(fieldName), fieldName, cellValue,typeName,pattern);
                    if (StringUtils.isNotBlank(result)){
                        mayError = String.format("第%s行%s", i + 1, result);
                    }
                }
            }

            if (nullCount == fieldNameList.size()) {
                continue;
            } else if(mayError != null){
                return error(mayError);
            }

            if (entity instanceof TaskLibrary) {
                homeorexpreSource = homeorexpreSource.add(((TaskLibrary) entity).getTasklibrary_source());

                Map<String, Object> isMap = isBrackets(entity);
                entity = (T) isMap.get("TaskLibrary");
                if (!Boolean.parseBoolean(String.valueOf(isMap.get("flag")))) {
                    return error(String.format("第%s行%s", i + 1, isMap.get("msg")));
                }

            } else if (entity instanceof ExpreLibrary) {
                homeorexpreSource = homeorexpreSource.add(((ExpreLibrary) entity).getExprelibrary_source());

                Map<String, Object> isMap = isBrackets(entity);
                if (!Boolean.parseBoolean(String.valueOf(isMap.get("flag")))) {
                    return error(String.format("第%s行%s", i + 1, isMap.get("msg")));
                }
                if (i == startLine) {
                    break;
                }
            }

            objects.add(entity);
        }

        return success(objects, homeorexpreSource);
    }


    /***
     * 读取单元格的值
     *
     * @param cell
     * @return
     */
    private String getCellValue(Cell cell) {
        Object result = "";
        if (cell != null) {
            switch (cell.getCellType()) {
                case Cell.CELL_TYPE_STRING:
                    result = cell.getStringCellValue();
                    break;
                case Cell.CELL_TYPE_NUMERIC:
                    DecimalFormat df = new DecimalFormat("#");//转换成整型
                    return df.format(cell.getNumericCellValue());
                case Cell.CELL_TYPE_BOOLEAN:
                    result = cell.getBooleanCellValue();
                    break;
                case Cell.CELL_TYPE_FORMULA:
                    result = cell.getCellFormula();
                    break;
                case Cell.CELL_TYPE_ERROR:
                    result = cell.getErrorCellValue();
                    break;
                case Cell.CELL_TYPE_BLANK:
                    break;
                default:
                    break;
            }
        }
        return result.toString();
    }

    //判断某字符结尾是否是以中文或英文括号 1选择 2判断 3填空 4简答
    public Map<String, Object> isBrackets(Object obj) {
        boolean flag = false;
        String msg = "";
        Map<String, Object> returnMap = new HashMap<String, Object>();
        String str = "";
        String optionMsg = "";
        String ansquesContent = null;
        int type = 0;
        String returnStr = "";
        if (obj instanceof TaskLibrary) {
            obj = (TaskLibrary) obj;
            str = String.valueOf(((TaskLibrary) obj).getTasklibrary_name());
            str = isStr(str);
            ((TaskLibrary) obj).setTasklibrary_name(str);
            optionMsg = String.valueOf(((TaskLibrary) obj).getTasklibrary_optionMsg());
            optionMsg = isStr(optionMsg);
            ((TaskLibrary) obj).setTasklibrary_optionMsg(optionMsg);
            ansquesContent = String.valueOf(((TaskLibrary) obj).getTasklibrary_answer());
            ansquesContent = isStr(ansquesContent);
            ((TaskLibrary) obj).setTasklibrary_answer(ansquesContent);
            type = Integer.parseInt(String.valueOf(((TaskLibrary) obj).getTasklibrary_type()));
            flag = isNum(String.valueOf(((TaskLibrary) obj).getTasklibrary_source()));
            returnMap.put("TaskLibrary",(TaskLibrary)obj);
            if (!flag) {
                returnMap.put("flag", flag);
                returnMap.put("msg", "的分数输入不正确，请按照正确提示输入分数");
                return returnMap;
            }
            switch (type) {
                case 1:
                    returnStr = PubMethods.isStr(optionMsg);
                    String arr[] = returnStr.split("#");
                    if (arr.length >= 2) {
                        flag = true;
                    } else {
                        flag = false;
                        msg = "的选项输入不正确，请按照正确提示输入选项";
                    }
                    break;
                case 2:
                    if (ansquesContent.equals("T") || ansquesContent.equals("F")) {
                        flag = true;
                        break;
                    } else {
                        flag = false;
                        msg = "的答案输入不正确，请按照正确提示输入答案";
                    }
                    break;
                case 3:
                    returnStr = PubMethods.isStr(str);
                    if (returnStr.contains("(+)")) {
                        returnStr = PubMethods.isStr(ansquesContent);
                        String aaa[] = returnStr.split(",");
                        if (aaa.length > 0) {
                            flag = true;
                        } else {
                            flag = false;
                            msg = "题目的格式输入不正确，请按照正确提示输入";
                        }
                    } else {
                        flag = false;
                        msg = "题目的格式输入不正确，请按照正确提示输入";
                    }
                    break;
                case 4:
                    flag = true;
                    break;
                case 5:
                    returnStr = PubMethods.isStr(optionMsg);
                    String arr1[] = returnStr.split("#");
                    if (arr1.length >= 2) {
                        flag = true;
                    } else {
                        flag = false;
                        msg = "的选项输入不正确，请按照正确提示输入选项";
                    }
                    break;
                default:
                    flag = false;
                    break;
            }
        }
        if (obj instanceof ExpreLibrary) {
            flag = isNum(String.valueOf(((ExpreLibrary) obj).getExprelibrary_source()));
            if (!flag) {
                returnMap.put("flag", flag);
                returnMap.put("msg", "的分数输入不正确，请按照正确提示输入分数");
                return returnMap;
            }
        }

        returnMap.put("flag", flag);
        returnMap.put("msg", msg);
        return returnMap;
    }

    public String isStr(String str) {
        if (str.contains("，")) {
            str = str.replace("，", ",");
        }
        if (str.contains("（") && str.contains("）")) {
            str = str.replace("（", "(");
            str = str.replace("）", ")");
        }
        return str;
    }

    public boolean isNum(String source) {
        try {
            BigDecimal source1 = new BigDecimal(source);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    public String setFields(T entity, Field field, String fieldName, String c,String typeName, Pattern pattern) {
        // 取得类型,并根据对象类型设置值.
        Class<?> fieldType = field.getType();
        int tasklibrary_type = 0;
        String msg = "";

        try {
            if ((fieldName.equals("tasklibrary_optionMsg")&& (c.equals("") || c == null))) {
                if(StringUtils.isNoneBlank(typeName)&&
                    typeName.equals(HomeworkOrExpreEnum.CHOICE.getMessage()) || typeName.equals(HomeworkOrExpreEnum.MANY_CHOICE.getMessage())){
                        return "数据不可以为空";
                    }
            }
            /* if((!fieldName.equals("tasklibrary_optionMsg")&&(c.equals("")||c==null))&&(StringUtils.isNoneBlank(typeName)&&
                    !typeName.equals(HomeworkOrExpreEnum.CHOICE.getMessage()) &&!typeName.equals(HomeworkOrExpreEnum.MANY_CHOICE.getMessage()))){
                return "数据不可以为空";
            }*/
            //到时候给楼上做课，屏蔽知识点
            if(!fieldName.equals("tasklibrary_optionMsg")&&!fieldName.equals("tasklibrary_knowpoint")&&(c.equals("")||c==null)
                    &&!typeName.equals(HomeworkOrExpreEnum.CHOICE.getMessage()) &&!typeName.equals(HomeworkOrExpreEnum.MANY_CHOICE.getMessage())){
                return "数据不可以为空";
            }
            if (fieldName.equals("tasklibrary_typeName")) {
                if (c.equals(HomeworkOrExpreEnum.CHOICE.getMessage()) || c.equals(HomeworkOrExpreEnum.MANY_CHOICE.getMessage()) || c.equals(HomeworkOrExpreEnum.JUDGE.getMessage()) || c.equals(HomeworkOrExpreEnum.BLANKS.getMessage()) || c.equals(HomeworkOrExpreEnum.ANWSER.getMessage())) {
                    if (c.equals(HomeworkOrExpreEnum.CHOICE.getMessage())) {
                        tasklibrary_type = HomeworkOrExpreEnum.CHOICE.getCode();
                    }
                    if (c.equals(HomeworkOrExpreEnum.MANY_CHOICE.getMessage())) {
                        tasklibrary_type = HomeworkOrExpreEnum.MANY_CHOICE.getCode();
                    }
                    if (c.equals(HomeworkOrExpreEnum.JUDGE.getMessage())) {
                        tasklibrary_type = HomeworkOrExpreEnum.JUDGE.getCode();
                    }
                    if (c.equals(HomeworkOrExpreEnum.BLANKS.getMessage())) {
                        tasklibrary_type = HomeworkOrExpreEnum.BLANKS.getCode();
                    }
                    if (c.equals(HomeworkOrExpreEnum.ANWSER.getMessage())) {
                        tasklibrary_type = HomeworkOrExpreEnum.ANWSER.getCode();
                    }
                    field = entity.getClass().getDeclaredField("tasklibrary_type");
                    entity.getClass().getMethod("set" + StringUtils.capitalize("tasklibrary_type"), field.getType()).invoke(entity, tasklibrary_type);
                    return "";
                } else {
                    msg = c + HomeworkOrExpreEnum.QUESTION_TYPE_ERROR.getMessage();
                    LOGGER.error(c + HomeworkOrExpreEnum.QUESTION_TYPE_ERROR.getMessage());
                }
            }
            if (fieldName.equals("tasklibrary_optionMsg")) {
                if (c == null || c.equals("")) {
                    entity.getClass().getMethod("set" + StringUtils.capitalize(fieldName), field.getType()).invoke(entity, "");
                }
            }

            if (fieldName.equals("exprelibrary_source") || fieldName.equals("tasklibrary_source")) {
                if (!pattern.matcher(c).matches()) {
                    return "分数填写不正确";
                }
            }

            if (String.class == fieldType) {
                entity.getClass().getMethod("set" + StringUtils.capitalize(fieldName), field.getType()).invoke(entity, c);
            } else if ((Integer.TYPE == fieldType)
                    || (Integer.class == fieldType)) {
                if (c.indexOf(".") != -1) {
                    entity.getClass().getMethod("set" + StringUtils.capitalize(fieldName), field.getType()).invoke(entity, Integer.parseInt(c.substring(0, c.indexOf("."))));
                } else {
                    entity.getClass().getMethod("set" + StringUtils.capitalize(fieldName), field.getType()).invoke(entity, Integer.parseInt(c));
                }
            } else if ((Long.TYPE == fieldType)
                    || (Long.class == fieldType)) {
                if (c.indexOf(".") != -1) {
                    entity.getClass().getMethod("set" + StringUtils.capitalize(fieldName), field.getType()).invoke(entity, Long.parseLong(c.substring(0, c.indexOf("."))));
                } else {
                    entity.getClass().getMethod("set" + StringUtils.capitalize(fieldName), field.getType()).invoke(entity, Long.parseLong(c));
                }
            } else if ((Float.TYPE == fieldType)
                    || (Float.class == fieldType)) {
                entity.getClass().getMethod("set" + StringUtils.capitalize(fieldName), field.getType()).invoke(entity, Float.valueOf(c));
            } else if ((Short.TYPE == fieldType)
                    || (Short.class == fieldType)) {
                entity.getClass().getMethod("set" + StringUtils.capitalize(fieldName), field.getType()).invoke(entity, Short.valueOf(c));
                if (c.indexOf(".") != -1) {
                    entity.getClass().getMethod("set" + StringUtils.capitalize(fieldName), field.getType()).invoke(entity, Short.valueOf(c.substring(0, c.indexOf("."))));
                } else {
                    entity.getClass().getMethod("set" + StringUtils.capitalize(fieldName), field.getType()).invoke(entity, Short.valueOf(c));
                }
            } else if ((Double.TYPE == fieldType)
                    || (Double.class == fieldType)) {
                entity.getClass().getMethod("set" + StringUtils.capitalize(fieldName), field.getType()).invoke(entity, Double.valueOf(c));
            } else if ((BigDecimal.class == fieldType)) {
                entity.getClass().getMethod("set" + StringUtils.capitalize(fieldName), field.getType()).invoke(entity, new BigDecimal(c));
            } else if ((Date.class == fieldType)) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                Date date = sdf.parse(c);
                entity.getClass().getMethod("set" + StringUtils.capitalize(fieldName), field.getType()).invoke(entity, date);
            }
        } catch (IllegalAccessException e) {
            LOGGER.error("参数异常!", e);
        } catch (InvocationTargetException e) {
            LOGGER.error("setter方法产生异常!", e);
        } catch (NoSuchMethodException e) {
            LOGGER.error("未找到 " + "set" + StringUtils.capitalize(fieldName) + " 方法!", e);
        } catch (Exception e) {
            LOGGER.error(field.getName() + "数据错误!", e);
        }
        return msg;
    }

}
